/**
 *
 */
package br.com.doclayer.service;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;

import br.com.doclayer.AddContentMode;
import br.com.doclayer.ContentMetadata;
import br.com.doclayer.FolderMetadata;
import br.com.doclayer.ItemIterable;
import br.com.doclayer.ObjectMetadata;
import br.com.doclayer.exceptions.DocLayerCommunicationException;
import br.com.doclayer.exceptions.DocLayerContentNotFoundException;
import br.com.doclayer.exceptions.DocLayerDuplicateContentException;

/**
 * Camada de Serviço para interoperabilidade com Sistemas de Gestão de Conteúdo
 * (CMS) que implementem o padrão CMIS (www.open-cmis.org).
 *
 * @author marcelo
 * @author helder
 * @author glauco
 */
public interface DocService {

  /**
   * Cria uma nova pasta dentro da pasta especificada através do parâmetro
   * <code>parentFolderUuid</code> com o nome informado no parâmtro
   * <code>newFolderName</code>
   *
   * @param parentFolderUuid
   *          uuid da pasta que conterá a nova pasta
   * @param newFolderName
   *          nome da nova pasta a ser criada
   * @return uma instância de <code>FolderMetadata</code> com os metadados da
   *         pasta criada
   */
  public FolderMetadata createFolder(String parentFolderUuid,
      String newFolderName) throws DocLayerCommunicationException,
      DocLayerDuplicateContentException;

  public FolderMetadata createFolderTree(String folderPath)
      throws DocLayerCommunicationException, DocLayerDuplicateContentException;

  /**
   * Adiciona o arquivo especificado no parâmetro <code>file</code> nas pastas
   * com UUIDs especificados em <code>foldersUuid</code>.
   *
   * O arquivo será adicionado a primeira pasta especificada e nas demais serão
   * adicionadas apenas referências.
   *
   * @param file
   *          arquivo
   * @param foldersUuid
   *          lista de UUIDs referente as pastas que receberão o arquivo
   * @return uma instância de <code>ContentMetadata</code> referente ao arquivo
   *         criado
   */
  public ContentMetadata addContent(File file, AddContentMode addContentMode,
      String... foldersUuid) throws DocLayerCommunicationException,
      DocLayerDuplicateContentException, DocLayerContentNotFoundException,
      FileNotFoundException;

  /**
   * Adiciona o arquivo especificado no parâmetro <code>inputStream</code> e
   * <code>contentName</code> nas pastas com UUIDs especificados em
   * <code>foldersUuid</code>.
   *
   * O arquivo será adicionado a primeira pasta especificada e nas demais serão
   * adicionadas apenas referências.
   *
   * @param inputStream
   * @param contentName
   * @param contentSize
   * @param foldersUuid
   *          lista de UUIDs referente as pastas que receberão o arquivo
   * @return uma instância de <code>ContentMetadata</code> referente ao arquivo
   *         criado
   */
  public ContentMetadata addContent(InputStream inputStream,
      String contentName, long contentSize, boolean createFolder,
      AddContentMode addContentMode, String... foldersUuid)
      throws DocLayerCommunicationException, DocLayerDuplicateContentException,
      DocLayerContentNotFoundException;

  /**
   * Exclui um objeto (pasta, arquivo, etc.) a partir do caminho ou do UUID
   * especificado.
   *
   * Se o objeto especificado for uma pasta, todo o seu conteúdo será excluído.
   *
   * @param pathOrUuid
   *          caminho ou UUID do objeto que será removido
   */
  public void removeObject(String pathOrUuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Exclui um objeto (pasta, arquivo, etc.) a partir de uma instância de
   * objectMetadata.
   *
   * Se o objeto especificado for uma pasta, todo o seu conteúdo será excluído.
   *
   * @param objectMetadata
   *          instância referente ao objeto a ser excluído
   */
  public void removeObject(ObjectMetadata objectMetadata)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  public ItemIterable<ContentMetadata> findContent(String where);

  /**
   * Retorna a instância de ObjectMetadata referente ao path ou uuid passado por
   * parâmetro
   *
   * @param pathOrUuid
   *          uuid do conteúdo desejado
   * @return instância de ObjectMetadata
   */
  public ObjectMetadata getObjectMetadata(String pathOrUuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Retorna a instância de ContentMetadata referente ao path ou uuid passados
   * por parâmetro
   *
   * @param pathOrUuid
   *          uuid do conteúdo desejado
   * @return instância de ContentMetadata
   */
  public ContentMetadata getContentMetadata(String pathOrUuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Retorna uma instância de FolderMetadata referente ao path ou uuid passados
   * por parâmetro
   *
   * @param pathOrUuid
   *          uuid da pasta desejada
   * @return instância de FolderMetadata
   */
  public FolderMetadata getFolderMetadata(String pathOrUuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Retorna uma lista de ObjectMetadata referente ao conteúdo da pasta
   * identificada pelo path ou uuid passado por parâmetro
   *
   * @param uuid
   *          caminho ou uuid da pasta desejada
   * @return uma lista de ObjectMetadata
   */
  public List<ObjectMetadata> getFolderChildren(String uuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  public void moveFolderContents(String origFolder, String destFolder,
      boolean removeOrigFolder) throws DocLayerCommunicationException,
      DocLayerContentNotFoundException;

  /**
   * Retorna o tamanho em bytes do conteúdo da pasta identificada pelo path ou
   * UUID passado por parâmetro.
   *
   * Este método deve ser executado com cuidado, pois é uma operação que requer
   * muito processamento no servidor.
   *
   * @param uuid
   *          caminho ou UUID da pasta desejada
   * @return tamanho em bytes ocupado pelos documentos contidos na pasta
   *         especificada
   */
  public long getFolderSize(String pathOrUuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Retorna um InputStream referente a um conteúdo especificado através do path
   * ou uuid passados por parâmetro
   *
   * @param uuid
   *          caminho ou uuid do conteúdo desejado
   * @return inputStream para realizar o download do conteúdo
   */
  public InputStream getContentStream(String uuid)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

  /**
   * Retorna um InputStream referente a um conteúdo especificado através de uma
   * instância de contentMetadata passada por parâmetro
   *
   * @param contentMetadata
   *          instância referente ao objeto a ser recuperado
   * @return inputStream para realizar o download do conteúdo
   */
  public InputStream getContentStream(ContentMetadata contentMetadata)
      throws DocLayerCommunicationException, DocLayerContentNotFoundException;

}
